package pl.edu.agh.agents.gui;

import java.awt.Color;
import java.awt.Point;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import pl.edu.agh.agents.agent.Agent;
import pl.edu.agh.agents.agent.AgentStrategy;
import pl.edu.agh.agents.agent.AutonomousAgent;
import pl.edu.agh.agents.agent.ControlledAgent;
import pl.edu.agh.agents.agent.SystemManager;
import pl.edu.agh.agents.planner.AgentPlanner;
import pl.edu.agh.agents.planner.CentralPlanner;
import pl.edu.agh.agents.state.State;
import pl.edu.agh.agents.state.StateSpace;
import pl.edu.agh.agents.xml.XMLConfiguration;
import pl.edu.agh.agents.xml.XMLState;

import com.thoughtworks.xstream.XStream;

public class GraphLoader {
	private static GraphLoader instance = new GraphLoader();

	private GraphLoader() {}

	public static GraphLoader getInstance() {
		return instance;
	}

	public void loadGraphFromFile(GUI gui, List<State> states, List<Agent> agents, String filename) {
		BufferedReader br = null;
		List<Point> coords = new ArrayList<Point>();

		try {
			br = new BufferedReader(new InputStreamReader(new FileInputStream(filename)));
		}

		catch (FileNotFoundException e) {
			gui.showErrorMsg("Nie znaleziono pliku " + filename);
			return;
		}

		try {
			XStream xstream = new XStream();
			Class<?>[] classes = { Agent.class, AutonomousAgent.class, ControlledAgent.class, XMLState.class, AgentStrategy.class, XMLConfiguration.class };
			xstream.processAnnotations(classes);
			xstream.setMode(XStream.NO_REFERENCES);

			XMLConfiguration conf = (XMLConfiguration)xstream.fromXML(br);

			for (XMLState xmlState : conf.getStates()) {
				State state = new State(xmlState.getID(), xmlState.isSink(), xmlState.getEnteringProb());

				Point point = new Point(xmlState.getX(), xmlState.getY());

				states.add(state);
				coords.add(point);
			}
			GraphUtils.getInstance().setCoords(coords);

			// ustawianie sasiadow na podstawie ID
			for (XMLState xmlState : conf.getStates()) {
				for (int neighborID : xmlState.getNeighborIDs()) {
					int stateID = xmlState.getID();
					State neighbor = states.get(neighborID);

					states.get(stateID).addNeighbor(neighbor);
				}
			}

			for (Agent agent : conf.getAgents()) {
				State currentState = states.get(agent.getCurrentState().getID());
				State goalState = states.get(agent.getGoalState().getID());

				agent.setStartState(currentState);
				agent.setCurrentState(currentState);
				agent.setGoalState(goalState);

				if (agent instanceof AutonomousAgent) {
					((AutonomousAgent) agent).setPlanner(new AgentPlanner(agent));
				}
				else {
					CentralPlanner.getInstance().addAgent(agent);
				}

				StateSpace.getInstance().addGoalState(agent, goalState);
				SystemManager.getInstance().addAgent(agent);

				currentState.setAgent(agent);

				Color color = conf.getColors().get(agent.getID());
				if (color == null) {
					color = conf.getColors().get(agent.getID());
				}
				gui.setAgentColor(agent, color);

			}
		}
		finally {
			try {
				br.close();
			} catch (IOException e1) {
			}
		}
	}
}